package com.fatri.lessionsimple.opengl.drawer

import android.content.Context
import android.opengl.GLES20
import android.opengl.GLSurfaceView
import com.fatri.lessionsimple.opengl.OpenGLTools
import com.fatri.lessionsimple.opengl.VaryTools
import java.nio.ByteBuffer
import java.nio.ByteOrder
import java.nio.FloatBuffer
import java.nio.ShortBuffer
import javax.microedition.khronos.egl.EGLConfig
import javax.microedition.khronos.opengles.GL10

class TransferRander(ctx: Context) : GLSurfaceView.Renderer {
    private lateinit var cube: Cube
    private lateinit var tools: VaryTools

    init {
        cube = Cube(ctx)
        tools = VaryTools()
    }


    override fun onSurfaceCreated(gl: GL10?, config: EGLConfig?) {
        GLES20.glClearColor(1.0f, 1.0f, 1.0f, 1.0f)

        //开启深度测试
        GLES20.glEnable(GLES20.GL_DEPTH_TEST)
        cube.create()

    }

    override fun onSurfaceChanged(gl: GL10?, width: Int, height: Int) {
        GLES20.glViewport(0, 0, width, height)
        val rate = width / height.toFloat()
        tools.ortho(-rate * 6, rate * 6, -6f, 6f, 3f, 20f)
        tools.setCamera(0f, 0f, 10f, 0f, 0f, 0f, 0f, 1f, 0f)

    }

    override fun onDrawFrame(gl: GL10?) {
        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT or GLES20.GL_DEPTH_BUFFER_BIT)

        cube.setMatrix(tools.getFinalMatrix())
        cube.draw()   //常态


        /**
         * y轴正方向评平移3
         */
        tools.pushMatrix()
        tools.translate(0f, 3f, 0f)  //矩阵的角标是竖着数
        cube.setMatrix(tools.getFinalMatrix())
        cube.draw()
        tools.popMatrix()

        /**
         * y轴向下平移3
         * 从（0，0，0）到（1，1，1）旋转30°
         */
        tools.pushMatrix()
        tools.translate(0f, -3f, 0f)
        tools.rotate(30f, 1f, 1f, 1f)
        cube.setMatrix(tools.getFinalMatrix())
        cube.draw()
        tools.popMatrix()

        /**
         * x轴负方向平移，然后按xyz->(0,0,0)到(1,-1,1)旋转120度，在放大到0.5倍
         */
        tools.pushMatrix()
        tools.translate(-3f, 0f, 0f)
        tools.scale(0.5f, 0.5f, 0.5f)


        //在以上变换的基础上再进行变换
        tools.pushMatrix()
        tools.translate(12f, 0f, 0f)
        tools.scale(1.0f, 2.0f, 1.0f)
        tools.rotate(30f, 1f, 2f, 1f)
        cube.setMatrix(tools.getFinalMatrix())
        cube.draw()
        tools.popMatrix()
    }


    fun translate(dx: Float, dy: Float) {
        tools.reset()
        tools.pushMatrix()
        tools.translate(dx, dy, 0f)
        cube.setMatrix(tools.getFinalMatrix())
        cube.draw()
        tools.popMatrix()
    }


    fun rotate(angle: Float, x: Float, y: Float, z: Float) {
        tools.reset()
        tools.pushMatrix()
        tools.rotate(angle, x, y, z)
        cube.setMatrix(tools.getFinalMatrix())
        cube.draw()
        tools.popMatrix()
    }
}


class Cube(val ctx: Context) {
    val cubePositions = floatArrayOf(
        -1.0f, 1.0f, 1.0f,  //正面左上0
        -1.0f, -1.0f, 1.0f,  //正面左下1
        1.0f, -1.0f, 1.0f,  //正面右下2
        1.0f, 1.0f, 1.0f,  //正面右上3
        -1.0f, 1.0f, -1.0f,  //反面左上4
        -1.0f, -1.0f, -1.0f,  //反面左下5
        1.0f, -1.0f, -1.0f,  //反面右下6
        1.0f, 1.0f, -1.0f
    )
    val index = shortArrayOf(
        6, 7, 4, 6, 4, 5,  //后面
        6, 3, 7, 6, 2, 3,  //右面
        6, 5, 1, 6, 1, 2,  //下面
        0, 3, 2, 0, 2, 1,  //正面
        0, 1, 5, 0, 5, 4,  //左面
        0, 7, 3, 0, 4, 7
    )

    var color = floatArrayOf(
        0f, 1f, 0f, 1f,
        0f, 1f, 0f, 1f,
        0f, 1f, 0f, 1f,
        0f, 1f, 0f, 1f,
        1f, 0f, 0f, 1f,
        1f, 0f, 0f, 1f,
        1f, 0f, 0f, 1f,
        1f, 0f, 0f, 1f
    )

    private lateinit var vertexBuf: FloatBuffer
    private lateinit var colorBuf: FloatBuffer

    private lateinit var indexBuf: ShortBuffer
    private var mProgram = 0
    private var hVertex = 0
    private var hColor = 0
    private var hMatrix = 0

    init {
        initData()
    }

    fun initData() {
        val bb = ByteBuffer.allocateDirect(cubePositions.size * 4)
        bb.order(ByteOrder.nativeOrder())
        vertexBuf = bb.asFloatBuffer()
        vertexBuf.put(cubePositions)
        vertexBuf.position(0)

        val cc = ByteBuffer.allocateDirect(color.size * 4)
        cc.order(ByteOrder.nativeOrder())
        colorBuf = cc.asFloatBuffer()
        colorBuf.put(color)
        colorBuf.position(0)

        val dd = ByteBuffer.allocateDirect(index.size * 2)
        dd.order(ByteOrder.nativeOrder())
        indexBuf = dd.asShortBuffer()
        indexBuf.put(index)
        indexBuf.position(0)

    }


    fun create() {
        mProgram = OpenGLTools.createProgram(ctx, "vary/vertex.glsl", "vary/fragment.glsl")
        hVertex = GLES20.glGetAttribLocation(mProgram, "vPosition")
        hColor = GLES20.glGetAttribLocation(mProgram, "aColor")
        hMatrix = GLES20.glGetUniformLocation(mProgram, "vMatrix")
    }

    private lateinit var matrix: FloatArray
    fun setMatrix(matrix: FloatArray) {
        this.matrix = matrix
    }

    fun draw() {
        GLES20.glUseProgram(mProgram)

        if (matrix != null) {
            GLES20.glUniformMatrix4fv(hMatrix, 1, false, matrix, 0)
        }

        GLES20.glEnableVertexAttribArray(hVertex)
        GLES20.glEnableVertexAttribArray(hColor)

        GLES20.glVertexAttribPointer(
            hVertex, 3, GLES20.GL_FLOAT
            , false, 0, vertexBuf
        )

        GLES20.glVertexAttribPointer(
            hColor, 4, GLES20.GL_FLOAT,
            false, 0, colorBuf
        )

        //索引法绘制
        GLES20.glDrawElements(
            GLES20.GL_TRIANGLE_STRIP, index.size, GLES20.GL_UNSIGNED_SHORT,
            indexBuf
        )

        //禁止顶点数组的句柄
        GLES20.glDisableVertexAttribArray(hVertex)
        GLES20.glDisableVertexAttribArray(hColor)
    }
}